
#ifndef MUTEX_H
#define MUTEX_H

#ifdef MY_USE_WIN32

    #include "Concurrent/Win32/MutexImp.hpp"

#elif MY_USE_UNIX

    #include "Concurrent/Unix/MutexImp.hpp"

#else

    #error No implementation defined for My::MutexImp.

#endif

namespace My
{
    /**
    *   @brief Mutex object for threads.
    *
    *   <p>The Mutex object support mutually exclusive execution of critical sections
    *   <b>beetween threads only</b>.
    */
    class Mutex : private MutexImp
    {
    public:
        /**
        *   @brief Constructor.
        *   @param is_recursive Enable recursion for the constructed Mutex.
        *
        *   <p>If recursion is enabled, a thread can lock the same Mutex several times and the
        *   Mutex won't be unlocked until a corresponding number of Unlock() calls have been
        *   made. The default is recursion disabled.</p>
        *
        *   @see Lock()
        *   @see TryLock()
        *   @see Unlock()
        */
        Mutex(bool is_recursive = false);

        /**
        *   @brief Destructor.
        *
        *   @warning Destroying a locked Mutex may result in undefined behaviour.
        */
        ~Mutex();

        /**
        *   @brief Lock this Mutex.
        *
        *   <p>If another thread has locked the Mutex then this call will block until that
        *   thread has unlocked it.
        *   Calling</p>
        *   <p>Calling this method multiple times on the same Mutex from the same thread is
        *   allowed if this mutex is a recursive Mutex.</p>
        *
        *   @warning If this mutex is a non-recursive
        *   Mutex, this method may <i>dead-lock</i> when the mutex is locked recursively.
        *
        *   @see Unlock()
        */
        void Lock();

        /**
        *   @brief Try to lock this Mutex.
        *
        *   <p>If the lock was obtained, the Mutex must be unlocked before another thread can
        *   successfully lock it.</p>
        *
        *   @return If the Mutex is not immediatly available or recursion is disabled and
        *   the calling thread is already the owner, the return value is false. Otherwise true.
        *
        *   @see Unlock()
        */
        bool TryLock();

        /**
        *   @brief Unlocks this Mutex.
        *
        *   @warning Attempting to unlock an unlocked Mutex results in an undefined behaviour.
        *   @warning Attempting to unlock a Mutex in a different thread to the one that locked
        *   it results in an undefined behaviour.
        *
        *   @see Lock()
        */
        void Unlock();
    };

    inline Mutex::Mutex(bool is_recursive)
        : MutexImp(is_recursive)
    {}

    inline Mutex::~Mutex()
    {}

    inline void Mutex::Lock()
    {
        MutexImp::Lock();
    }

    inline bool Mutex::TryLock()
    {
        return MutexImp::TryLock();
    }

    inline void Mutex::Unlock()
    {
        return MutexImp::Unlock();
    }
}

#endif // MUTEX_H
